import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;

import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.Vertex;
import edu.uci.ics.jung.io.GraphMLFile;


public class main {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {



		//Input:
		//The simulator takes as input the application consisting of an interacting set of tasks stored
		//in a GraphML file and the simulation time.

		//Get information about the tasks
		ArrayList<Task> tasks = new ArrayList<Task>();
		ArrayList<Integer> taskPeriods = new ArrayList<Integer>();
		Graph taskGraph = UtilizationTest.getTaskGraph();

		for (Iterator<Object> iter = taskGraph.getVertices().iterator(); iter.hasNext();) {
			Vertex v = (Vertex) iter.next();

			int taskPeriod = UtilizationTest.getPeriodValue(v);

			tasks.add(new Task(taskPeriod, UtilizationTest.getBCETValue(v), UtilizationTest.getWCETValue(v)));
			taskPeriods.add(taskPeriod);
		}

		//TEST
		/*for (Task task : tasks) {	
			System.out.println("Task: " + Integer.toString(task.period) + Integer.toString(task.bcet) + Integer.toString(task.wcet));
		}*/

		//Compute the scheduling length (overall running time)
		int cycles = 10; //number of cycles
		//int lcm = lcm(taskPeriods); //length of a cycle
		int lcm = 60;	//TESTING
		int n = cycles*lcm;	//number of time units - e.g. total running time

		//Calculate priorities
		//Issue: What if 2 priorities are equal?


		//Initialise all jobs for all cycles
		ArrayList<Job> jobs_queue = new ArrayList<Job>();
		Random randgen = new Random();


		for (Task task : tasks) {

			int j;
			int end_period = n/task.period;
			int jobRelease = 0;
			int jobTime = 0;
			for (j=1; j <= end_period; j++) {
				jobRelease = task.period*(j-1);	//multiply job with period to get starting time for every period
				
				if (task.wcet > task.bcet) {
				   jobTime = randgen.nextInt(task.wcet-task.bcet)+task.bcet;	//TODO: Q: Which distribution shall we use? Interested in avg. run, so uses uniformely distributed random method
				} else {
					//In case they are equal or wcet is lowest (from input)
					jobTime = 0;
				}
				
				
				Job newJob = new Job(task,jobRelease,jobTime);
				task.jobs.add(newJob);
				jobs_queue.add(newJob);
			}

		}

		//System.out.println("Job_queue: " + jobs_queue.size());

		//sort job queue: First after lowest job release time and then after highest priority
		//NO! Because put all jobs in from each task.
		
		//Simulate
		ArrayList<Job> ready_list = new ArrayList<Job>();
		Job current_job;
		int current_jobTime;

		int timeunit;
		for (timeunit = 1; timeunit <= n; timeunit++) {

			//Get released jobs after priority
			//a ready job is a job, that has already been released
			//TODO: Check that the jobs still are sorted after hightes priority
			for (Job job : jobs_queue) {
				if (job.getRelease() < timeunit) {
					ready_list.add(job);

				} else {
					break;	//because jobs_queue is sorted after release time
				}
			}
			//Treat jobs if any
			if (ready_list.size() > 0) {

				current_job = ready_list.get(0); //NB! ready list already sorted after highest priority because jobs_queue was sorted 
				current_jobTime = current_job.getTime()-1;	//Problem if jobTime is 0
				current_job.setTime(current_jobTime);

				//Job has finished
				if (current_jobTime == 0) {
					current_job.setResponse(timeunit); //Nej timeunit-job.starttime

					//Update worst-case response time of the task if necessary
					Task current_jobTask = current_job.getTask(); 	//Task which the current job belongs to
					if (current_job.getResponse() > current_jobTask.getWorstcase_response()) {
						current_jobTask.setWorstcase_response(timeunit); //shall be response
 					}

					//Remove finished job from the job queue
					jobs_queue.remove(current_job);
				}

			}	
		}
		for (Task task : tasks) {
			System.out.println("worst-case response time: " + task.getWorstcase_response());
		}
		
	}

}


